package com.hnec.dms.log.format;

import ch.qos.logback.classic.pattern.ThrowableProxyConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.contrib.json.classic.JsonLayout;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * json格式日志输出，扩展至logback，让自定义参数和原来的参数保持在同一级。
 * <p>
 * 增加logName和logId，logName：日志名称，用于ES的索引；logId唯一标示一条日志。
 *
 * @author hidebug
 */
public class LogJsonLayout extends JsonLayout {

    private String logName;

    public LogJsonLayout() {
        super();

        setThrowableProxyConverter(new CusThrowableProxyConverter());
    }

    @SuppressWarnings("rawtypes")
    @Override
    protected Map toJsonMap(ILoggingEvent event) {
        Map<String, Object> map = new LinkedHashMap<String, Object>();

        addTimestamp(TIMESTAMP_ATTR_NAME, this.includeTimestamp, event.getTimeStamp(), map);

        add("logName", true, logName, map);

        //TODO MX_H 后续考虑如何和链路跟踪的id结合起来
        add("logId", true, generatorUUID(), map);

        add(LEVEL_ATTR_NAME, this.includeLevel, String.valueOf(event.getLevel()), map);
        add(THREAD_ATTR_NAME, this.includeThreadName, event.getThreadName(), map);

        // 将mdc中的内容全部放到一级属性
        Map<String, String> mdcMap = event.getMDCPropertyMap();
        if (mdcMap != null && !mdcMap.isEmpty()) {
            map.putAll(mdcMap);
        }

        add(LOGGER_ATTR_NAME, this.includeLoggerName, event.getLoggerName(), map);
        add(FORMATTED_MESSAGE_ATTR_NAME, this.includeFormattedMessage, event.getFormattedMessage(), map);
        add(MESSAGE_ATTR_NAME, this.includeMessage, event.getMessage(), map);
        add(CONTEXT_ATTR_NAME, this.includeContextName, event.getLoggerContextVO().getName(), map);
        addThrowableInfo(EXCEPTION_ATTR_NAME, this.includeException, event, map);
        addCustomDataToJsonMap(map, event);

        return map;
    }


    // 自定义转化器，logback默认取第一个参数作为异常栈输出的大小，这点有点粗糙？
    private static class CusThrowableProxyConverter extends ThrowableProxyConverter {

        public CusThrowableProxyConverter() {
            List<String> optionList = getOptionList();
            if (optionList == null) {
                optionList = new ArrayList<String>();
                setOptionList(optionList);
            }
            optionList.add(0, "50");
        }
    }

    public void setLogName(String logName) {
        this.logName = logName;
    }

    /**
     * 32 uuid生成方法，去掉字符间的-
     *
     * @return
     */
    //TODO MX_M 要和链路跟踪统一ID，目前是临时做法
    private String generatorUUID() {
        String uuid = UUID.randomUUID().toString().replace("-", "");

        return uuid;
    }


}
